package cn.tedu.charging.order.amqp;

import cn.tedu.charging.common.constant.AmqpComponentConst;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.order.service.AmqpConsumerService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 负责监听延迟队列 拿到json转化delayCheckMessage 调用业务处理
 */
@Component
@Slf4j
public class AmqpDelayConsumer {
    @Autowired
    private AmqpConsumerService amqpConsumerService;
    /**
     * 将消费业务逻辑 单独封装调用业务层
     * 消费者任务比较集中
     * 1. 解析消息 将消息反序列化 成业务对象
     * 2. 调用业务处理延迟逻辑
     * 3. 根据业务处理结果 使用channel确认
     * @param message
     * @param channel
     */
    @RabbitListener(queues = AmqpComponentConst.DELAY_BILL_DL_QUEUE)
    public void handleDelayMsg(Message message, Channel channel){
        //1.从message拿到body数据 反序列化转化成DelayCheckMessage
        DelayCheckMessage delayMsg = ProducerClient.deserializer(message.getBody(), DelayCheckMessage.class);
        boolean handleResult=false;
        //2.调用业务层处理
        try{
            handleResult=amqpConsumerService.handleDelayMessage(delayMsg);
        }catch (Exception e){
            log.error("延迟消息消费 异常",e);
        }
        //3.根据业务处理的结果 判断本次消费成功和失败
        try{
            if (handleResult){
                //消费成功
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }else{
                //消费失败的原因 多种 不同情况不一定允许重新入队
                //消费者本次异常类型 是因为某些资源访问超时(数据库 redis链不上) 重新消费可能恢复的
                //消费者本次异常类型 是因为消息和业务不兼容 不匹配 重复没有意义
                channel.basicReject(
                        message.getMessageProperties().getDeliveryTag(),
                        true);
            }
        }catch (Exception e){
            log.error("消息消费 确认失败,请检查",e);
        }
    }
}
